import 'package:flutter/material.dart';
import 'package:flutter_lui/flutter_lui.dart';
import 'package:flutter_lui/src/l_style.dart';

/// 默认进度条宽度
final _defaultStockWidth = lrpx(10);

/// 默认间隙比例总份数
const _defaultPaddingRate = 5;

/// 悬浮提示框宽度
final _popWidth = lrpx(32);

class LProgress extends StatefulWidget {
  /// 进度条长度
  final double? width;

  /// 进度条宽度
  final double? stockWidth;

  /// 进度条背景色
  final Color? backgroundColor;

  /// 进度条前景色
  final Color? foregroundColor;

  /// 进度条值
  final double? value;

  /// 圆角
  final double? radius;

  /// 是否禁用
  final bool? disabled;

  /// 进度条变化回调
  final void Function(double value)? onChange;
  const LProgress(
      {this.width,
      this.stockWidth,
      this.backgroundColor,
      this.foregroundColor,
      this.value,
      this.radius,
      this.disabled,
      this.onChange,
      Key? key})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => _LProgress();
}

class _LProgress extends State<LProgress> with TickerProviderStateMixin {
  /// 能显示的总长度
  double progressTotalWidth = 0;
  late AnimationController controller;

  /// 两次显示差的比例
  double progressRate = 0;

  /// 旧值
  double oldValue = 0;

  /// 新值
  double value = 0;

  /// 拖动开始时的位置
  double startWidth = 0;

  /// 是否显示悬浮提示框
  bool showPop = false;

  @override
  void initState() {
    super.initState();
    value = widget.value ?? 0;
    if (value > 1) value = 1;
    if (value < 0) value = 0;
    controller = AnimationController(
        lowerBound: 0,
        upperBound: 1,
        vsync: this,
        duration: const Duration(milliseconds: 100));
    controller.addListener(() {
      setState(() {
        progressRate = controller.value;
        if (controller.isCompleted) {
          oldValue = value;
        }
      });
    });
    controller.forward();
  }

  @override
  didUpdateWidget(LProgress oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.value != oldWidget.value) {
      value = widget.value ?? 0;
      if (value > 1) value = 1;
      if (value < 0) value = 0;
      if (oldValue != value) {
        controller.reset();
        controller.forward();
      }
    }
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  /// 首次加载完成 计算总长度
  handleDidUpdate(LPostFrameInfoValue v) {
    var useStockWidth = widget.stockWidth ?? _defaultStockWidth;
    progressTotalWidth = v.width - useStockWidth / _defaultPaddingRate * 2;
  }

  handleTap() {
    startWidth = 0;
    setState(() {
      showPop = false;
    });
  }

  handleDragStart(DragDownDetails detail) {
    startWidth = detail.globalPosition.dx;
    setState(() {
      showPop = true;
    });
  }

  handleDrag(DragUpdateDetails detail) {
    if (widget.onChange == null) return;
    var currWidth = detail.globalPosition.dx;
    value = value + (currWidth - startWidth) / PageSize.width;
    if (value > 1) value = 1;
    if (value < 0) value = 0;
    oldValue = value;
    setState(() {});
    startWidth = currWidth;
  }

  handleDragEnd(DragEndDetails detail) {
    startWidth = 0;
    setState(() {
      showPop = false;
    });
    if (widget.onChange != null && widget.disabled != true) {
      widget.onChange!(value);
    }
  }

  @override
  Widget build(BuildContext context) {
    var useStockWidth = widget.stockWidth ?? _defaultStockWidth;
    var useBackgroundColor =
        widget.backgroundColor ?? LUI.instance.backgroundColor;
    var useBorderRadius = widget.radius ?? LStyle.borderRadius;
    var foregroundColor = widget.foregroundColor ?? LUI.instance.primaryColor;
    if (widget.disabled == true) {
      foregroundColor = foregroundColor.withOpacity(0.8);
    }
    var oldWidth = progressTotalWidth * oldValue;
    var newWidth = progressTotalWidth * value;
    var currWidth = oldWidth + (newWidth - oldWidth) * progressRate;
    var tipLeft = progressTotalWidth * value +
        useStockWidth / _defaultPaddingRate -
        _popWidth / 2;
    if (tipLeft < 0) tipLeft = 0;
    if (tipLeft + _popWidth > progressTotalWidth) {
      tipLeft = progressTotalWidth - _popWidth;
    }
    return LPostFrameInfo(
      callback: handleDidUpdate,
      child: LBox(
        onTap: handleTap,
        onPanDown: handleDragStart,
        onPanUpdate: widget.disabled == true ? null : handleDrag,
        onPanEnd: handleDragEnd,
        width: widget.width,
        height: useStockWidth,
        backgroundColor: useBackgroundColor,
        borderRadius: [useBorderRadius],
        child: Stack(clipBehavior: Clip.none, children: [
          showPop
              ? Positioned(
                  bottom: useStockWidth,
                  left: tipLeft,
                  child: LBox(
                    boxShadow: [
                      BoxShadow(
                          color: Colors.black.withOpacity(0.2),
                          offset: Offset(0, lrpx(0)),
                          blurRadius: lrpx(12),
                          spreadRadius: lrpx(0))
                    ],
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      LBox(
                        width: _popWidth,
                        height: _popWidth / 2,
                        backgroundColor: Colors.white,
                        borderRadius: [LStyle.borderRadius],
                        child: '${(value * 100).toInt()}',
                        alignment: Alignment.center,
                      ),
                      CustomPaint(
                        painter: _BorderPainter(
                          lineColor: LUI.instance.borderColor,
                        ),
                        child: ClipPath(
                          clipper: _TriangleClipper(),
                          child: Container(
                            width: lrpx(10),
                            height: lrpx(5),
                            color: Colors.white,
                          ),
                        ),
                      )
                    ],
                  ))
              : Container(),
          Positioned(
              top: useStockWidth / _defaultPaddingRate,
              left: useStockWidth / _defaultPaddingRate,
              child: LBox(
                backgroundColor: foregroundColor,
                width: currWidth,
                height: useStockWidth /
                    _defaultPaddingRate *
                    (_defaultPaddingRate - 2),
                borderRadius: [useBorderRadius],
              ))
        ]),
      ),
    );
  }
}

/// 画三角形
class _TriangleClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();

    /// 尖朝下
    path.moveTo(0, 0);
    path.lineTo(size.width, 0);
    path.lineTo(size.width / 2, size.height);

    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) {
    return oldClipper != this;
  }
}

/// 画三角形的边框
class _BorderPainter extends CustomPainter {
  final Color lineColor;
  _BorderPainter({required this.lineColor});
  @override
  void paint(Canvas canvas, Size size) {
    Paint p = Paint();
    p.color = lineColor;
    p.strokeWidth = lrpx(1);

    /// 尖朝下
    canvas.drawLine(const Offset(0, 0), Offset(size.width / 2, size.height), p);
    canvas.drawLine(
        Offset(size.width, 0), Offset(size.width / 2, size.height), p);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}
